/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2025-03-05 16:11:59
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2025-03-13 21:43:15
 * @FilePath: /lesson/Thread/Thread_package/Main.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include<iostream>
#include<unistd.h>
#include<cstdio>
#include <vector>
#include "thread_pack.hpp"
#include<pthread.h>

using namespace ThreadMoudle;
using namespace std;

int tickets=100;

pthread_mutex_t gmutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t gcond = PTHREAD_COND_INITIALIZER;

void routine(const string& name)
{
    while(true)
    {
        pthread_mutex_lock(&gmutex);//对于临界资源的访问和修改都需要加锁，因为保不齐在读取判断的时候，其他线程修改了，就导致判断有问题

        // if“判断和等待”是具有原子性的！必须在加锁和解锁之间！
        if(tickets>0)
        {
            
            usleep(5000);// 抢票1ms

            pthread_cond_wait(&gcond,&gmutex);

            printf("who : %s ,get a ticket: %d\n",name.c_str(),tickets);
            
            tickets--;
            
            

        }
        else
        {
            pthread_mutex_unlock(&gmutex);
            // 这个地方如果不是释放锁然后break，那么线程就是带着锁走的，就没有释放锁，其他线程也就拿不到锁
            break;
        }
        pthread_mutex_unlock(&gmutex);
    }
}

const int gnum=10;
int main()
{

    Thread t1("thread-1",routine);
    Thread t2("thread-2",routine);
    Thread t3("thread-3",routine);
    Thread t4("thread-4",routine);


    t1.Start();
    t2.Start();
    t3.Start();
    t4.Start();

    // 唤醒其他线程
    while(tickets > 0)
    {
        pthread_cond_signal(&gcond);
    
    }
    // sleep(1);
    // pthread_cond_broadcast(&gcond);

    t1.Join();
    t2.Join();
    t3.Join();
    t4.Join();
}